﻿namespace Lilium.LParse

type Step<'a> =
    //abstract Best :
    //    Step<'a>
    //    -> Step<'a>
    abstract Eval :
        unit
        -> 'a

module Step =

    open Lilium.LParse.Prelude

    let rec step (innerStep : Step<'a>) = 
        { new Step<'a> with 
            member x.Eval () = innerStep.Eval () }
            
    let fail = 
        { new Step<'a> with 
            member x.Eval () = failwith "should not happen" } // не будет происходить после реализации коррекции, но всегда ли нужна коррекция и сколько она будет жрать времени - вот в чём вопрос.

    let success value =
        { new Step<'a> with 
            member x.Eval () = value }

    let apply f (step : Step<'a>) =
        { new Step<'b> with 
            member x.Eval () = f (step.Eval()) }

    let push value step =
        apply (fun s -> (value, s)) step

    (*
    let rec best l r =
        match l, r with
        | l, Fail        -> l
        | Fail, r        -> r
        | Step l, Step r -> Step (best l r)
        | _, _           -> failwith "incorrect parser"

    let rec eval s =
        match s with
        | Step s -> eval s // если заменяем на seq тут будет `раскручивание' оной
        | Done v -> v
        | Fail   -> failwith "should not happen"
    *)